﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

using Lucene.Net.Documents;

using ERPStore.Extensions;

using CloudSoft.Extensions;

namespace ERPStore.Indexers.Lucene.Models
{
	public static class ModelConverter
	{
		public static Document ToDocument(this ERPStore.Models.Product product)
		{
			var catalogService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICatalogService>();

			var fp = new System.Globalization.CultureInfo(1033);
			fp.NumberFormat.NumberDecimalSeparator = ".";
			fp.NumberFormat.CurrencyDecimalSeparator = ".";

			var document = new global::Lucene.Net.Documents.Document();

			// Product.BestPrice;
			if (product.Brand != null)
			{
				document.Add(new Field("BrandId", product.Brand.Id.ToString(), Field.Store.YES, Field.Index.ANALYZED));
			}
			if (product.Category != null)
			{
				document.Add(new Field("CategoryId", product.Category.Id.ToString(), Field.Store.YES, Field.Index.ANALYZED));
			}
			document.Add(new Field("Code", product.Code, Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("CreationDate", product.CreationDate.ToLongTimeString(), Field.Store.YES, Field.Index.ANALYZED));
			if (product.DefaultImage != null)
			{
				document.Add(new Field("DefaultImageId", product.DefaultImage.Id.ToString(), Field.Store.YES, Field.Index.NO));
				document.Add(new Field("DefaultImageUrl", product.DefaultImage.Url, Field.Store.YES, Field.Index.NO));
				if (product.DefaultImage.ExternalUrl != null)
				{
					document.Add(new Field("DefaultImageExternalUrl", product.DefaultImage.ExternalUrl.ToLower(), Field.Store.YES, Field.Index.NO));
				}
			}
			document.Add(new Field("DefaultTaxRate", product.DefaultTaxRate.ToString(fp), Field.Store.YES, Field.Index.NO));
			document.Add(new Field("Id", product.Id.ToString(), Field.Store.YES, Field.Index.ANALYZED));

			var keywords = catalogService.GetProductKeywords(product);
			if (!keywords.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("Keywords", keywords, Field.Store.YES, Field.Index.ANALYZED));
			}
			document.Add(new Field("LastUpdate", product.LastUpdate.ToLongTimeString(), Field.Store.YES, Field.Index.NO));
			if (!product.Link.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("Link", product.Link, Field.Store.YES, Field.Index.ANALYZED));
			}
			// Product.LocalizationList;
			if (!product.LongDescription.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("LongDescription", product.LongDescription, Field.Store.YES, Field.Index.ANALYZED));
			}
			if (!product.ManufacturerUrl.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("BrandUrl", product.ManufacturerUrl.ToLower(), Field.Store.YES, Field.Index.NO));
			}
			document.Add(new Field("MetricId", product.Metric.Id.ToString(), Field.Store.YES, Field.Index.NO));
			document.Add(new Field("MinimumSaleQuantity", product.MinimumSaleQuantity.ToString(), Field.Store.YES, Field.Index.NO));
			document.Add(new Field("OrderCount", product.OrderCount.ToString(), Field.Store.YES, Field.Index.NO));
			// Product.Packaging;
			document.Add(new Field("PackagingValue", product.Packaging.Value.ToString(), Field.Store.YES, Field.Index.NO));
			document.Add(new Field("PackagingIsSplittable", product.Packaging.IsSplittable.ToString(), Field.Store.YES, Field.Index.NO));
			if (!product.PageDescription.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("PageDescription", product.PageDescription, Field.Store.YES, Field.Index.NO));
			}
			if (!product.PageTitle.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("PageTitle", product.PageTitle, Field.Store.YES, Field.Index.NO));
			}
			if (product.PriceByQuantityList.IsNotNullOrEmpty())
			{
				foreach (var item in product.PriceByQuantityList)
				{

				}
			}
			if (product.RecyclePrice != null)
			{
				document.Add(new Field("RecyclePrice", product.RecyclePrice.Value.ToString(fp), Field.Store.YES, Field.Index.NO));
			}
			document.Add(new Field("SaleMode", product.SaleMode.ToString(), Field.Store.YES, Field.Index.NO));
			document.Add(new Field("IsSellable", product.IsSellable ? "1" : "0", Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("HasPicture", product.HasPicture ? "1" : "0", Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("SalePrice", product.SalePrice.Value.ToString(fp), Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("SalePriceSort", string.Format("{0:000000000000000}", product.SalePrice.Value * 1000000), Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("SaleUnitValue", product.SaleUnitValue.ToString(), Field.Store.YES, Field.Index.NO));
			if (!product.ShortDescription.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("ShortDescription", product.ShortDescription, Field.Store.YES, Field.Index.ANALYZED));
			}
			if (product.StorageRank.HasValue)
			{
				document.Add(new Field("StorageRank", product.StorageRank.Value.ToString(), Field.Store.YES, Field.Index.NO));
			}
			if (!product.StrengthsPoints.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("StrengthsPoints", product.StrengthsPoints, Field.Store.YES, Field.Index.ANALYZED));
			}
			document.Add(new Field("Title", product.Title, Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("BlocTitle", product.Title.Replace(" ", "xxx"), Field.Store.YES, Field.Index.ANALYZED));
			if (product.Shipping != null)
			{
				document.Add(new Field("Transport.Level", product.Shipping.Level.ToString(), Field.Store.YES, Field.Index.NO));
				document.Add(new Field("Transport.Strategy", product.Shipping.Strategy.ToString(), Field.Store.YES, Field.Index.NO));
				document.Add(new Field("Transport.FixedPrice", product.Shipping.FixedPrice.ToString(fp), Field.Store.YES, Field.Index.NO));
			}
			document.Add(new Field("Weight", product.Weight.ToString(), Field.Store.YES, Field.Index.NO));
			if (product.IsParentVariation)
			{
				document.Add(new Field("HasStock", "1", Field.Store.YES, Field.Index.ANALYZED));
			}
			else
			{
				document.Add(new Field("HasStock", product.HasStock ? "1" : "0", Field.Store.YES, Field.Index.ANALYZED));
			}

			if (!product.Gtin.EAN.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("GTIN.EAN", product.Gtin.EAN, Field.Store.YES, Field.Index.ANALYZED));
			}
			if (!product.Gtin.UPC.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("GTIN.UPC", product.Gtin.UPC, Field.Store.YES, Field.Index.ANALYZED));
			}

			if (!product.ManufacturerPartNumber.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("ManufacturerPartNumber", product.ManufacturerPartNumber, Field.Store.YES, Field.Index.ANALYZED));
			}

			if (product.VariationProductParentId.HasValue)
			{
				document.Add(new Field("VariationProductParentId", product.VariationProductParentId.Value.ToString(), Field.Store.YES, Field.Index.NO));
				document.Add(new Field("IsVariant", "1", Field.Store.YES, Field.Index.ANALYZED));
			}
			else
			{
				document.Add(new Field("IsVariant", "0", Field.Store.YES, Field.Index.ANALYZED));
			}

			document.Add(new Field("IsParentVariation", product.IsParentVariation ? "1" : "0", Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("IsPack", product.IsPack ? "1" : "0", Field.Store.YES, Field.Index.ANALYZED));

			if (product.ExtendedProperties != null)
			{
				int i = 0;
				foreach (var propertyGroup in product.ExtendedProperties)
				{
					document.Add(new Field(string.Format("PropertyGroupName{0}", i), propertyGroup.Key.Name, Field.Store.YES, Field.Index.NO));
					document.Add(new Field(string.Format("PropertyGroupDescription{0}", i), propertyGroup.Key.Description, Field.Store.YES, Field.Index.NO));
					i++;
					foreach (var property in propertyGroup.Value)
					{
						if (property.Value.IsNullOrTrimmedEmpty())
						{
							continue;
						}
						document.Add(new Field(string.Format("ExtendedProperties.{0}", property.Key), property.Value, Field.Store.YES, Field.Index.ANALYZED));
					}
				}
			}

			if (!product.SortPropertyDictionary.IsNullOrEmpty())
			{
				foreach (var item in product.SortPropertyDictionary.Keys)
				{
					var value = product.SortPropertyDictionary[item];
					if (value.IsNullOrTrimmedEmpty())
					{
						continue;
					}
					document.Add(new Field(string.Format("Sort.{0}", item), value, Field.Store.NO, Field.Index.NOT_ANALYZED));
				}
			}

			if (!product.Warranty.IsNullOrTrimmedEmpty())
			{
				document.Add(new Field("Warranty", product.Warranty, Field.Store.YES, Field.Index.ANALYZED));
			}

			
			document.Add(new Field("Stats.OrderCount", product.Stats.OrderCount.ToString(), Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("Stats.SaleTotal", string.Format(fp, "{0}", product.Stats.SaleTotal.GetValueOrDefault(0)), Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("Stats.VisitorCount", product.Stats.VisitorCount.ToString(), Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("Stats.DistinctCustomerCount", product.Stats.DistinctCustomerCount.ToString(), Field.Store.YES, Field.Index.ANALYZED));

			if (product.PriceType == ERPStore.Models.PriceType.Catalog)
			{
				document.Add(new Field("ProductPriceType", "1", Field.Store.YES, Field.Index.ANALYZED));
			}
			else
			{
				document.Add(new Field("ProductPriceType", "0", Field.Store.YES, Field.Index.ANALYZED));
			}

			var documentService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.IDocumentService>();

			var list = documentService.GetMediaList(product);
			if (product.DefaultImage != null)
			{
				list.RemoveAll(i => i.Id == product.DefaultImage.Id);
			}
			var pictureList = new List<ERPStore.Models.Media>();
			int imageCount = 0;
			int documentCount = 0;
			if (!list.IsNullOrEmpty())
			{
				var allowedExtensionList = new List<string>()
				{
					".gif"
					,".jpg"
					,".png"
					,".jpeg"
					,".bmp"
				};

				imageCount = list.Where(i => allowedExtensionList.Any(j => j.Equals(i.GetExtension(null), StringComparison.InvariantCultureIgnoreCase))).Count();
				documentCount = list.Count - imageCount;
			}
			if (product.DefaultImage != null)
			{
				imageCount++;
			}
			document.Add(new Field("ImageCount", imageCount.ToString(), Field.Store.YES, Field.Index.ANALYZED));
			document.Add(new Field("DocumentCount", documentCount.ToString(), Field.Store.YES, Field.Index.ANALYZED));

			return document;
		}

		public static ERPStore.Models.Product ToProduct(this Document doc)
		{
			var catalogService = GlobalConfiguration.Configuration.DependencyResolver.GetService<ERPStore.Services.ICatalogService>();

			var fp = new System.Globalization.CultureInfo(1033);
			fp.NumberFormat.NumberDecimalSeparator = ".";
			fp.NumberFormat.CurrencyDecimalSeparator = ".";

			var product = new ERPStore.Models.Product();
			product.Id = Convert.ToInt32(doc.Get("Id"));
			product.Code = doc.Get("Code");
			product.Title = doc.Get("Title");
			product.Packaging = new ERPStore.Models.Packaging()
			{
				Value = Convert.ToInt32(doc.Get("PackagingValue")),
				IsSplittable = doc.Get("IsSplittable") == "0" ? false : true,
			};
			product.SaleUnitValue = Convert.ToInt32(doc.Get("SaleUnitValue"));
			product.ShortDescription = doc.Get("ShortDescription");
			product.LongDescription = doc.Get("LongDescription");
			product.Keywords = doc.Get("Keywords");
			//product.IsPromotion = doc.Get("IsPromotion") == "0" ? false : true;
			//product.IsDestock = doc.Get("IsDestock") == "0" ? false : true;
			//product.IsFirstPrice = doc.Get("IsFirstPrice") == "0" ? false : true;
			//product.IsNew = doc.Get("IsNew") == "0" ? false : true;
			//product.IsTopSell = doc.Get("IsTopSell") == "0" ? false : true;
			product.Link = doc.Get("Link");
			product.PageDescription = doc.Get("PageDescription");
			product.PageTitle = doc.Get("PageTitle");
			product.StrengthsPoints = doc.Get("StrengthsPoints");
			product.Weight = Convert.ToInt32(doc.Get("Weight"));
			product.CreationDate = Convert.ToDateTime(doc.Get("CreationDate"));
			product.ManufacturerUrl = doc.Get("BrandUrl");
			product.DefaultTaxRate = Convert.ToDouble(doc.Get("DefaultTaxRate"), fp);
			product.HasStock = doc.Get("HasStock") == "0" ? false : true;
			product.OrderCount = Convert.ToInt32(doc.Get("OrderCount"));
			product.MinimumSaleQuantity = Convert.ToInt32(doc.Get("MinimumSaleQuantity"));
			product.Metric = ERPStore.Models.Metric.GetByKey(Convert.ToInt32(doc.Get("MetricId")));
			product.LastUpdate = Convert.ToDateTime(doc.Get("LastUpdate"));

			if (!doc.Get("SaleMode").IsNullOrTrimmedEmpty())
			{
				var saleMode = doc.Get("SaleMode");
				product.SaleMode = (ERPStore.Models.ProductSaleMode)Enum.Parse(typeof(ERPStore.Models.ProductSaleMode), saleMode);
			}

			if (!doc.Get("SalePrice").IsNullOrTrimmedEmpty())
			{
				var sp = doc.Get("SalePrice");
				product.SalePrice = new ERPStore.Models.Price(Convert.ToDecimal(sp, fp), product.DefaultTaxRate);
			}

			if (!doc.Get("RecyclePrice").IsNullOrTrimmedEmpty())
			{
				product.RecyclePrice = new ERPStore.Models.Price(Convert.ToDecimal(doc.Get("RecyclePrice"), fp), product.DefaultTaxRate);
			}

			if (!doc.Get("CategoryId").IsNullOrTrimmedEmpty())
			{
				var value = doc.Get("CategoryId");
				product.Category = catalogService.GetCategoryById(Convert.ToInt32(doc.Get("CategoryId")));
			}

			if (!doc.Get("BrandId").IsNullOrTrimmedEmpty())
			{
				product.Brand = catalogService.GetBrandById(Convert.ToInt32(doc.Get("BrandId")));
			}

			if (!doc.Get("DefaultImageId").IsNullOrTrimmedEmpty())
			{
				product.DefaultImage = new ERPStore.Models.Media()
				{
					Id = doc.Get("DefaultImageId"),
					Url = doc.Get("DefaultImageUrl"),
					ExternalUrl = doc.Get("DefaultImageExternalUrl"),
				};
			}

			if (!doc.Get("Transport.Strategy").IsNullOrTrimmedEmpty())
			{
				product.Shipping.Strategy = (ERPStore.Models.FeeTransportStrategy)Enum.Parse(typeof(ERPStore.Models.FeeTransportStrategy), doc.Get("Transport.Strategy"));
				product.Shipping.Level = Convert.ToInt32(doc.Get("Transport.Level"));
				product.Shipping.FixedPrice = Convert.ToDecimal(doc.Get("Transport.FixedPrice"), fp);
			}

			product.Gtin.EAN = doc.Get("GTIN.EAN");
			product.Gtin.UPC = doc.Get("GTIN.UPC");
			product.ManufacturerPartNumber = doc.Get("ManufacturerPartNumber");

			if (doc.Get("VariationProductParentId") != null)
			{
				product.VariationProductParentId = Convert.ToInt32(doc.Get("VariationProductParentId"));
			}

			product.IsParentVariation = doc.Get("IsParentVariation") == "0" ? false : true;
			product.IsPack = doc.Get("IsPack") == "0" ? false : true;

			ERPStore.Models.PropertyGroup pg = null;
			var properties = new Dictionary<string, string>();
			foreach (global::Lucene.Net.Documents.Field item in doc.GetFields())
			{
				if (item.Name().StartsWith("PropertyGroupName"))
				{
					pg = new ERPStore.Models.PropertyGroup();
					pg.Name = item.StringValue();
				}
				if (item.Name().StartsWith("PropertyGroupDescription"))
				{
					pg.Description = item.StringValue();
				}
				if (item.Name().StartsWith("ExtendedProperties."))
				{
					if (product.ExtendedProperties == null)
					{
						product.ExtendedProperties = new ERPStore.Models.ExtendedPropertyList();
					}
					var propertyName = item.Name().Replace("ExtendedProperties.", "");
					if (!product.ExtendedProperties.ContainsKey(pg))
					{
						var dic = new Dictionary<string, string>();
						dic.Add(propertyName, item.StringValue());
						product.ExtendedProperties.Add(pg, dic);
					}
					else
					{
						product.ExtendedProperties[pg].Add(propertyName, item.StringValue());
					}
				}
				if (item.Name().StartsWith("Sort."))
				{
					var sortName = item.Name().Replace("Sort.", "");
					product.SortPropertyDictionary.Add(sortName, item.StringValue());
				}
			}

			if (!doc.Get("Warranty").IsNullOrTrimmedEmpty())
			{
				product.Warranty = doc.Get("Warranty");
			}

			// Récupération des stats
			product.Stats.OrderCount = doc.Get<int?>("Stats.OrderCount");
			product.Stats.SaleTotal = doc.Get<decimal?>("Stats.SaleTotal");
			product.Stats.VisitorCount = doc.Get<int?>("Stats.VisitorCount");
			product.Stats.DistinctCustomerCount = doc.Get<int?>("Stats.DistinctCustomerCount");

			product.PriceType = ERPStore.Models.PriceType.Normal;
			var priceTypeString = doc.Get("ProductPriceType");
			if (priceTypeString == "1")
			{
				product.PriceType = ERPStore.Models.PriceType.Catalog;
			}

			product.ImageCount = doc.Get<int>("ImageCount");
			product.DocumentCount = doc.Get<int>("DocumentCount");

			return product;
		}

	}
}
